package com.boot.watermark;

import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.font.constants.StandardFonts;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.Canvas;
import org.apache.commons.lang.StringUtils;


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class WatermarkPDFUtils {

    public static void main(String[] args) throws IOException {
        addWatermark(new TextWatermark11(), "C:\\Users\\Administrator\\Desktop\\未命名1.pdf", "C:\\Users\\Administrator\\Desktop\\未命名2.pdf");
    }

    /**
     * 添加文字水印； 默认为居中添加
     *
     * @param watermark
     * @param srcPath   原始 PDF 文件绝对路径
     * @param destPath  添加完水印后的 PDF 存放路径
     */
    public static void addWatermark(TextWatermark11 watermark, String srcPath, String destPath) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(srcPath), new PdfWriter(destPath));
        Document doc = new Document(pdfDoc);
        PdfFont font = getPdfFont(watermark.getFontPath());

        // 设置文字水印样式
        final String text = watermark.getText();
        final int fontSize = watermark.getFontSize();
        Paragraph paragraph = new Paragraph(text)
                .setFont(font)
                .setFontColor(new DeviceRgb(0, 0, 0))
                .setOpacity(watermark.getOpacity()) // 字体透明度 0-1 完全透明~不透明
                .setFontSize(fontSize); // 字体大小
        final String color = watermark.getColor();
        // 设置 RGB 颜色
        if (color != null) {
            final String[] rgbs = color.split(",");
            final DeviceRgb deviceRgb = new DeviceRgb(
                    Integer.parseInt(rgbs[0].trim()),
                    Integer.parseInt(rgbs[1].trim()),
                    Integer.parseInt(rgbs[2].trim()));
            paragraph.setFontColor(deviceRgb);
        } else {
            paragraph.setFontColor(new DeviceRgb(Color.lightGray));
        }

        // 获取水印文字宽度
        final float textWidth = font.getWidth(text, fontSize);
        // 文字高度则是字体大小
        final float textHeight = fontSize;
        final int tileMode = watermark.getTileMode();
        final int pageModeOfHorizontalInterval = watermark.getPageModeOfHorizontalInterval() == null ? 50 : watermark.getPageModeOfHorizontalInterval();
        final int pageModeOfVerticalInterval = watermark.getPageModeOfVerticalInterval() == null ? (int) textHeight : watermark.getPageModeOfVerticalInterval();

        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfPage pdfPage = pdfDoc.getPage(i);
            // 获取页面大小，考虑页面旋转
            Rectangle pageSize = pdfPage.getPageSizeWithRotation();
            // 当页面有旋转时，内容自动旋转
            pdfPage.setIgnorePageRotationForContent(true);

            // 水印水平垂直居中
            if (tileMode == 1) {
                // 计算添加的位置坐标：这里使用居中位置，水平垂直居中
                float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
                float y = (pageSize.getTop() + pageSize.getBottom()) / 2;

                // 参数分别为：文本、x 坐标、y 坐标、添加到底几页、文本水平对齐方式、文本垂直对齐方式、旋转弧度
                doc.showTextAligned(paragraph,
                        x, // 文本所在 x y 坐标，文字将围绕这个点进行对齐或则旋转
                        y,
                        i, // 添加到 PDF 第几页
                        TextAlignment.CENTER,   // 文本水平对齐方式
                        VerticalAlignment.TOP, // 文本垂直对齐方式
                        // 将 角度 转换为 弧度
                        (float) Math.toRadians(watermark.getRadAngle()));
            } else {
                // 水印按照设置平铺页面

                // 注意这里的坐标点是 文字中心点，所以宽度需要增加文字自己的宽度，否则会重合在一起
//                for (float posX = 0f; posX < pageSize.getWidth(); posX = posX + textWidth + pageModeOfHorizontalInterval) {
//                    for (float posY = pageModeOfVerticalInterval; posY < pageSize.getHeight(); posY = posY + pageModeOfVerticalInterval) {
//                        // 参数分别为：文本、x 坐标、y 坐标、添加到底几页、文本水平对齐方式、文本垂直对齐方式、旋转弧度
//                        doc.showTextAligned(paragraph,
//                                posX, // 文本所在 x y 坐标，文字将围绕这个点进行对齐或则旋转
//                                posY,
//                                i, // 添加到 PDF 第几页
//                                TextAlignment.CENTER,   // 文本水平对齐方式
//                                VerticalAlignment.TOP, // 文本垂直对齐方式
//                                // 将 角度 转换为 弧度
//                                (float) Math.toRadians(watermark.getRadAngle()));
//                    }
//                }
                System.out.println((int) pageSize.getWidth());
                int xw = ((int) pageSize.getWidth()) / 5;
                for (int x = 0; x < 2; x++) {
                    int xx = 0;
                    if (x == 0) {
                        xx = xw;
                    }
                    if (x == 1) {
                        xx = (int) pageSize.getWidth() - xw - 50;
                    }
                    for (float posY = pageModeOfVerticalInterval; posY < pageSize.getHeight() + 500; posY = posY + pageModeOfVerticalInterval) {
                        // 参数分别为：文本、x 坐标、y 坐标、添加到底几页、文本水平对齐方式、文本垂直对齐方式、旋转弧度
                        doc.showTextAligned(paragraph,
                                xx, // 文本所在 x y 坐标，文字将围绕这个点进行对齐或则旋转
                                posY,
                                i, // 添加到 PDF 第几页
                                TextAlignment.CENTER,   // 文本水平对齐方式
                                VerticalAlignment.TOP, // 文本垂直对齐方式
                                // 将 角度 转换为 弧度
                                (float) Math.toRadians(watermark.getRadAngle()));
                    }
                }
            }
        }
        doc.close();
    }

    /**
     * 获取字体，支持 afm、pfm、ttf、otf、woff、woff2 字体，ttc 目前直接报错
     *
     * @param fontPath 字体文件绝对路径，如果为空则返回默认的英文字体
     * @return
     */
    private static PdfFont getPdfFont(String fontPath) throws IOException {
        if (StringUtils.isEmpty(fontPath)) {
            return PdfFontFactory.createFont(StandardFonts.HELVETICA);
        }
        return PdfFontFactory.createFont(
                fontPath,
                // 水平书写
                PdfEncodings.IDENTITY_H,
                // 是否将字体嵌入到目标文档中: 如果可能，嵌入字体
                PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
    }

    /**
     * 添加图片水印； 默认为居中添加
     *
     * @param watermark
     * @param srcPath   原始 PDF 文件绝对路径
     * @param destPath  添加完水印后的 PDF 存放路径
     */
    public static void addWatermark(ImageWatermark watermark, String srcPath, String destPath) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(srcPath), new PdfWriter(destPath));
        Document doc = new Document(pdfDoc);

        // 创建图片
        ImageData img = ImageDataFactory.create(watermark.getPath());
        float w = img.getWidth();
        float h = img.getHeight();

        // 设置透明度
        PdfExtGState gs1 = new PdfExtGState().setFillOpacity(watermark.getOpacity());

        // 循环添加到每一页的 PDF 中
        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfPage pdfPage = pdfDoc.getPage(i);
            // 获取页面大小，考虑页面旋转
            Rectangle pageSize = pdfPage.getPageSizeWithRotation();
            // 当页面有旋转时，内容自动旋转
            pdfPage.setIgnorePageRotationForContent(true);

            // 计算添加的位置坐标：这里使用居中位置，水平垂直居中
            float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
            float y = (pageSize.getTop() + pageSize.getBottom()) / 2;

            if (watermark.getTileMode() == 1) {
                // 添加图片水印使用.
                PdfCanvas over = new PdfCanvas(pdfDoc.getPage(i));
                over.saveState();
                over.setExtGState(gs1);

                // 添加图片水印：位置水平垂直居中
                over.addImageWithTransformationMatrix(img, w, 0, 0, h, x - (w / 2), y - (h / 2), false);
                over.restoreState();
            } else {
                double height = pageSize.getHeight();
                double width = pageSize.getWidth();
                final int pageModeOfHorizontalInterval = watermark.getPageModeOfHorizontalInterval() == null ? 50 : watermark.getPageModeOfHorizontalInterval();
                final int pageModeOfVerticalInterval = watermark.getPageModeOfVerticalInterval() == null ? (int) h : watermark.getPageModeOfVerticalInterval();
                Image image = new Image(img);
                for (float posX = 0f; posX < width; posX = posX + w / 2 + pageModeOfHorizontalInterval) {
                    for (float posY = pageModeOfVerticalInterval; posY < height; posY = posY + pageModeOfVerticalInterval) {

                        // 水印位置
                        image.setFixedPosition(posX, posY);
                        // 水印倾斜度
                        image.setRotationAngle(watermark.getRadAngle());

                        //  setFillOpacity 透明度
                        PdfExtGState gs = new PdfExtGState();
                        gs.setFillOpacity(watermark.getOpacity());
                        PdfCanvas canvas = new PdfCanvas(pdfPage.newContentStreamBefore(), pdfPage.getResources(), pdfDoc);
                        canvas.setExtGState(gs);

                        new Canvas(canvas, pdfDoc, pageSize).add(image);
                    }
                }
            }
        }

        doc.close();
    }


    //定义图片水印字体类型
    public static final String FONT_NAME = "微软雅黑";


    //定义图片水印字体加粗、变细、倾斜等样式
    public static final int FONT_STYLE = Font.BOLD;

    //设置字体大小
    public static final int FONT_SIZE = 120;

    //设置文字透明程度
    public static float ALPHA = 0.3F;

    /**
     * 给图片添加多个文字水印、可设置水印文字旋转角度
     * source 需要添加水印的图片路径
     * outPut 添加水印后图片输出路径
     * imageName 图片名称
     * imageType 图片类型
     * color 水印文字的颜色
     * word 水印文字
     * degree 水印文字旋转角度，为null表示不旋转
     */
    public Boolean png(String sourcePath, String outputPath, String imageName, String imageType, Color color, String word, Integer degree) {
        try {
            //读取原图片信息
            File file = new File(sourcePath);

            if (!file.isFile()) {
                return false;
            }

            //获取源图像的宽度、高度
            BufferedImage image = ImageIO.read(file);
            int width = image.getWidth(null);
            int height = image.getHeight(null);

            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

            //创建绘图工具对象
            Graphics2D graphics2D = bufferedImage.createGraphics();
            //其中的0代表和原图位置一样
            graphics2D.drawImage(image, 0, 0, width, height, null);

            //设置水印文字（设置水印字体样式、粗细、大小）
            graphics2D.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));

            //设置水印颜色
            graphics2D.setColor(color);

            //设置水印透明度
            graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));

            //设置水印旋转
            if (null != degree) {
                graphics2D.rotate(Math.toRadians(degree), (double) bufferedImage.getWidth() / 2, (double) bufferedImage.getHeight() / 2);
            }

            int x = width / 3;
            int y = FONT_SIZE;
            int space = height / FONT_SIZE;
            for (int i = 0; i < space; i++) {
                //如果最后一个坐标的y轴比height高，直接退出
                if ((y + FONT_SIZE) > height) {
                    break;
                }
                //进行绘制
                graphics2D.drawString(word, x, y);
                y += (2 * FONT_SIZE);
            }

            graphics2D.dispose();

            //输出图片
            File sf = new File(outputPath, imageName + "." + imageType);
            // 保存图片
            ImageIO.write(bufferedImage, imageType, sf);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }


}
